home *** CD-ROM | disk | FTP | other *** search
/ PC World 2006 July & August / PCWorld_2006-07-08_cd.bin / komunikace / apache / apache_2[1].2.2-win32-x86-no_ssl.msi / Data1.cab / _E309FC2C97CEC53D25196D7311F89867 < prev    next >
Extensible Markup Language  |  2006-01-15  |  48KB  |  1,289 lines

  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><!--
  4.         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  5.               This file is generated from xml source: DO NOT EDIT
  6.         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  7.       -->
  8. <title>URL Rewriting Guide - Advanced topics - Apache HTTP Server</title>
  9. <link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
  10. <link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
  11. <link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" />
  12. <link href="../images/favicon.ico" rel="shortcut icon" /></head>
  13. <body id="manual-page"><div id="page-header">
  14. <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
  15. <p class="apache">Apache HTTP Server Version 2.2</p>
  16. <img alt="" src="../images/feather.gif" /></div>
  17. <div class="up"><a href="./index.html"><img title="<-" alt="<-" src="../images/left.gif" /></a></div>
  18. <div id="path">
  19. <a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.2</a></div><div id="page-content"><div id="preamble"><h1>URL Rewriting Guide - Advanced topics</h1>
  20. <div class="toplang">
  21. <p><span>Available Languages: </span><a href="../en/rewrite/rewrite_guide_advanced.html" title="English"> en </a></p>
  22. </div>
  23.  
  24.  
  25.     <p>This document supplements the <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
  26.     <a href="../mod/mod_rewrite.html">reference documentation</a>.
  27.     It describes how one can use Apache's <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
  28.     to solve typical URL-based problems with which webmasters are
  29.     commonony confronted. We give detailed descriptions on how to
  30.     solve each problem by configuring URL rewriting rulesets.</p>
  31.  
  32.     <div class="warning">ATTENTION: Depending on your server configuration
  33.     it may be necessary to slightly change the examples for your
  34.     situation, e.g. adding the <code>[PT]</code> flag when
  35.     additionally using <code class="module"><a href="../mod/mod_alias.html">mod_alias</a></code> and
  36.     <code class="module"><a href="../mod/mod_userdir.html">mod_userdir</a></code>, etc. Or rewriting a ruleset
  37.     to fit in <code>.htaccess</code> context instead
  38.     of per-server context. Always try to understand what a
  39.     particular ruleset really does before you use it. This
  40.     avoids many problems.</div>
  41.  
  42.   </div>
  43. <div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#cluster">Webcluster through Homogeneous URL Layout</a></li>
  44. <li><img alt="" src="../images/down.gif" /> <a href="#structuredhomedirs">Structured Homedirs</a></li>
  45. <li><img alt="" src="../images/down.gif" /> <a href="#filereorg">Filesystem Reorganization</a></li>
  46. <li><img alt="" src="../images/down.gif" /> <a href="#redirect404">Redirect Failing URLs To Other Webserver</a></li>
  47. <li><img alt="" src="../images/down.gif" /> Archive Access Multiplexer</li>
  48. <li><img alt="" src="../images/down.gif" /> <a href="#content">Content Handling</a></li>
  49. <li><img alt="" src="../images/down.gif" /> <a href="#access">Access Restriction</a></li>
  50. </ul><h3>See also</h3><ul class="seealso"><li><a href="../mod/mod_rewrite.html">Module
  51. documentation</a></li><li><a href="rewrite_intro.html">mod_rewrite
  52. introduction</a></li><li><a href="rewrite_guide.html">Practical solutions to common
  53. problems</a></li><li><a href="rewrite_tech.html">Technical details</a></li></ul></div>
  54. <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  55. <div class="section">
  56. <h2><a name="cluster" id="cluster">Webcluster through Homogeneous URL Layout</a></h2>
  57.  
  58.       
  59.  
  60.       <dl>
  61.         <dt>Description:</dt>
  62.  
  63.         <dd>
  64.           <p>We want to create a homogeneous and consistent URL
  65.           layout over all WWW servers on a Intranet webcluster, i.e.
  66.           all URLs (per definition server local and thus server
  67.           dependent!) become actually server <em>independent</em>!
  68.           What we want is to give the WWW namespace a consistent
  69.           server-independent layout: no URL should have to include
  70.           any physically correct target server. The cluster itself
  71.           should drive us automatically to the physical target
  72.           host.</p>
  73.         </dd>
  74.  
  75.         <dt>Solution:</dt>
  76.  
  77.         <dd>
  78.           <p>First, the knowledge of the target servers come from
  79.           (distributed) external maps which contain information
  80.           where our users, groups and entities stay. The have the
  81.           form</p>
  82.  
  83. <div class="example"><pre>
  84. user1  server_of_user1
  85. user2  server_of_user2
  86. :      :
  87. </pre></div>
  88.  
  89.           <p>We put them into files <code>map.xxx-to-host</code>.
  90.           Second we need to instruct all servers to redirect URLs
  91.           of the forms</p>
  92.  
  93. <div class="example"><pre>
  94. /u/user/anypath
  95. /g/group/anypath
  96. /e/entity/anypath
  97. </pre></div>
  98.  
  99.           <p>to</p>
  100.  
  101. <div class="example"><pre>
  102. http://physical-host/u/user/anypath
  103. http://physical-host/g/group/anypath
  104. http://physical-host/e/entity/anypath
  105. </pre></div>
  106.  
  107.           <p>when the URL is not locally valid to a server. The
  108.           following ruleset does this for us by the help of the map
  109.           files (assuming that server0 is a default server which
  110.           will be used if a user has no entry in the map):</p>
  111.  
  112. <div class="example"><pre>
  113. RewriteEngine on
  114.  
  115. RewriteMap      user-to-host   txt:/path/to/map.user-to-host
  116. RewriteMap     group-to-host   txt:/path/to/map.group-to-host
  117. RewriteMap    entity-to-host   txt:/path/to/map.entity-to-host
  118.  
  119. RewriteRule   ^/u/<strong>([^/]+)</strong>/?(.*)   http://<strong>${user-to-host:$1|server0}</strong>/u/$1/$2
  120. RewriteRule   ^/g/<strong>([^/]+)</strong>/?(.*)  http://<strong>${group-to-host:$1|server0}</strong>/g/$1/$2
  121. RewriteRule   ^/e/<strong>([^/]+)</strong>/?(.*) http://<strong>${entity-to-host:$1|server0}</strong>/e/$1/$2
  122.  
  123. RewriteRule   ^/([uge])/([^/]+)/?$          /$1/$2/.www/
  124. RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3\
  125. </pre></div>
  126.         </dd>
  127.       </dl>
  128.  
  129.     </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  130. <div class="section">
  131. <h2><a name="structuredhomedirs" id="structuredhomedirs">Structured Homedirs</a></h2>
  132.  
  133.       
  134.  
  135.       <dl>
  136.         <dt>Description:</dt>
  137.  
  138.         <dd>
  139.           <p>Some sites with thousands of users usually use a
  140.           structured homedir layout, i.e. each homedir is in a
  141.           subdirectory which begins for instance with the first
  142.           character of the username. So, <code>/~foo/anypath</code>
  143.           is <code>/home/<strong>f</strong>/foo/.www/anypath</code>
  144.           while <code>/~bar/anypath</code> is
  145.           <code>/home/<strong>b</strong>/bar/.www/anypath</code>.</p>
  146.         </dd>
  147.  
  148.         <dt>Solution:</dt>
  149.  
  150.         <dd>
  151.           <p>We use the following ruleset to expand the tilde URLs
  152.           into exactly the above layout.</p>
  153.  
  154. <div class="example"><pre>
  155. RewriteEngine on
  156. RewriteRule   ^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*)  /home/<strong>$2</strong>/$1/.www$3
  157. </pre></div>
  158.         </dd>
  159.       </dl>
  160.  
  161.     </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  162. <div class="section">
  163. <h2><a name="filereorg" id="filereorg">Filesystem Reorganization</a></h2>
  164.  
  165.       
  166.  
  167.       <dl>
  168.         <dt>Description:</dt>
  169.  
  170.         <dd>
  171.           <p>This really is a hardcore example: a killer application
  172.           which heavily uses per-directory
  173.           <code>RewriteRules</code> to get a smooth look and feel
  174.           on the Web while its data structure is never touched or
  175.           adjusted. Background: <strong><em>net.sw</em></strong> is
  176.           my archive of freely available Unix software packages,
  177.           which I started to collect in 1992. It is both my hobby
  178.           and job to to this, because while I'm studying computer
  179.           science I have also worked for many years as a system and
  180.           network administrator in my spare time. Every week I need
  181.           some sort of software so I created a deep hierarchy of
  182.           directories where I stored the packages:</p>
  183.  
  184. <div class="example"><pre>
  185. drwxrwxr-x   2 netsw  users    512 Aug  3 18:39 Audio/
  186. drwxrwxr-x   2 netsw  users    512 Jul  9 14:37 Benchmark/
  187. drwxrwxr-x  12 netsw  users    512 Jul  9 00:34 Crypto/
  188. drwxrwxr-x   5 netsw  users    512 Jul  9 00:41 Database/
  189. drwxrwxr-x   4 netsw  users    512 Jul 30 19:25 Dicts/
  190. drwxrwxr-x  10 netsw  users    512 Jul  9 01:54 Graphic/
  191. drwxrwxr-x   5 netsw  users    512 Jul  9 01:58 Hackers/
  192. drwxrwxr-x   8 netsw  users    512 Jul  9 03:19 InfoSys/
  193. drwxrwxr-x   3 netsw  users    512 Jul  9 03:21 Math/
  194. drwxrwxr-x   3 netsw  users    512 Jul  9 03:24 Misc/
  195. drwxrwxr-x   9 netsw  users    512 Aug  1 16:33 Network/
  196. drwxrwxr-x   2 netsw  users    512 Jul  9 05:53 Office/
  197. drwxrwxr-x   7 netsw  users    512 Jul  9 09:24 SoftEng/
  198. drwxrwxr-x   7 netsw  users    512 Jul  9 12:17 System/
  199. drwxrwxr-x  12 netsw  users    512 Aug  3 20:15 Typesetting/
  200. drwxrwxr-x  10 netsw  users    512 Jul  9 14:08 X11/
  201. </pre></div>
  202.  
  203.           <p>In July 1996 I decided to make this archive public to
  204.           the world via a nice Web interface. "Nice" means that I
  205.           wanted to offer an interface where you can browse
  206.           directly through the archive hierarchy. And "nice" means
  207.           that I didn't wanted to change anything inside this
  208.           hierarchy - not even by putting some CGI scripts at the
  209.           top of it. Why? Because the above structure should be
  210.           later accessible via FTP as well, and I didn't want any
  211.           Web or CGI stuff to be there.</p>
  212.         </dd>
  213.  
  214.         <dt>Solution:</dt>
  215.  
  216.         <dd>
  217.           <p>The solution has two parts: The first is a set of CGI
  218.           scripts which create all the pages at all directory
  219.           levels on-the-fly. I put them under
  220.           <code>/e/netsw/.www/</code> as follows:</p>
  221.  
  222. <div class="example"><pre>
  223. -rw-r--r--   1 netsw  users    1318 Aug  1 18:10 .wwwacl
  224. drwxr-xr-x  18 netsw  users     512 Aug  5 15:51 DATA/
  225. -rw-rw-rw-   1 netsw  users  372982 Aug  5 16:35 LOGFILE
  226. -rw-r--r--   1 netsw  users     659 Aug  4 09:27 TODO
  227. -rw-r--r--   1 netsw  users    5697 Aug  1 18:01 netsw-about.html
  228. -rwxr-xr-x   1 netsw  users     579 Aug  2 10:33 netsw-access.pl
  229. -rwxr-xr-x   1 netsw  users    1532 Aug  1 17:35 netsw-changes.cgi
  230. -rwxr-xr-x   1 netsw  users    2866 Aug  5 14:49 netsw-home.cgi
  231. drwxr-xr-x   2 netsw  users     512 Jul  8 23:47 netsw-img/
  232. -rwxr-xr-x   1 netsw  users   24050 Aug  5 15:49 netsw-lsdir.cgi
  233. -rwxr-xr-x   1 netsw  users    1589 Aug  3 18:43 netsw-search.cgi
  234. -rwxr-xr-x   1 netsw  users    1885 Aug  1 17:41 netsw-tree.cgi
  235. -rw-r--r--   1 netsw  users     234 Jul 30 16:35 netsw-unlimit.lst
  236. </pre></div>
  237.  
  238.           <p>The <code>DATA/</code> subdirectory holds the above
  239.           directory structure, i.e. the real
  240.           <strong><em>net.sw</em></strong> stuff and gets
  241.           automatically updated via <code>rdist</code> from time to
  242.           time. The second part of the problem remains: how to link
  243.           these two structures together into one smooth-looking URL
  244.           tree? We want to hide the <code>DATA/</code> directory
  245.           from the user while running the appropriate CGI scripts
  246.           for the various URLs. Here is the solution: first I put
  247.           the following into the per-directory configuration file
  248.           in the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>
  249.           of the server to rewrite the announced URL
  250.           <code>/net.sw/</code> to the internal path
  251.           <code>/e/netsw</code>:</p>
  252.  
  253. <div class="example"><pre>
  254. RewriteRule  ^net.sw$       net.sw/        [R]
  255. RewriteRule  ^net.sw/(.*)$  e/netsw/$1
  256. </pre></div>
  257.  
  258.           <p>The first rule is for requests which miss the trailing
  259.           slash! The second rule does the real thing. And then
  260.           comes the killer configuration which stays in the
  261.           per-directory config file
  262.           <code>/e/netsw/.www/.wwwacl</code>:</p>
  263.  
  264. <div class="example"><pre>
  265. Options       ExecCGI FollowSymLinks Includes MultiViews
  266.  
  267. RewriteEngine on
  268.  
  269. #  we are reached via /net.sw/ prefix
  270. RewriteBase   /net.sw/
  271.  
  272. #  first we rewrite the root dir to
  273. #  the handling cgi script
  274. RewriteRule   ^$                       netsw-home.cgi     [L]
  275. RewriteRule   ^index\.html$            netsw-home.cgi     [L]
  276.  
  277. #  strip out the subdirs when
  278. #  the browser requests us from perdir pages
  279. RewriteRule   ^.+/(netsw-[^/]+/.+)$    $1                 [L]
  280.  
  281. #  and now break the rewriting for local files
  282. RewriteRule   ^netsw-home\.cgi.*       -                  [L]
  283. RewriteRule   ^netsw-changes\.cgi.*    -                  [L]
  284. RewriteRule   ^netsw-search\.cgi.*     -                  [L]
  285. RewriteRule   ^netsw-tree\.cgi$        -                  [L]
  286. RewriteRule   ^netsw-about\.html$      -                  [L]
  287. RewriteRule   ^netsw-img/.*$           -                  [L]
  288.  
  289. #  anything else is a subdir which gets handled
  290. #  by another cgi script
  291. RewriteRule   !^netsw-lsdir\.cgi.*     -                  [C]
  292. RewriteRule   (.*)                     netsw-lsdir.cgi/$1
  293. </pre></div>
  294.  
  295.           <p>Some hints for interpretation:</p>
  296.  
  297.           <ol>
  298.             <li>Notice the <code>L</code> (last) flag and no
  299.             substitution field ('<code>-</code>') in the forth part</li>
  300.  
  301.             <li>Notice the <code>!</code> (not) character and
  302.             the <code>C</code> (chain) flag at the first rule
  303.             in the last part</li>
  304.  
  305.             <li>Notice the catch-all pattern in the last rule</li>
  306.           </ol>
  307.         </dd>
  308.       </dl>
  309.  
  310.     </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  311. <div class="section">
  312. <h2><a name="redirect404" id="redirect404">Redirect Failing URLs To Other Webserver</a></h2>
  313.  
  314.       
  315.  
  316.       <dl>
  317.         <dt>Description:</dt>
  318.  
  319.         <dd>
  320.           <p>A typical FAQ about URL rewriting is how to redirect
  321.           failing requests on webserver A to webserver B. Usually
  322.           this is done via <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> CGI-scripts in Perl, but
  323.           there is also a <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> solution.
  324.           But notice that this performs more poorly than using an
  325.           <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code>
  326.           CGI-script!</p>
  327.         </dd>
  328.  
  329.         <dt>Solution:</dt>
  330.  
  331.         <dd>
  332.           <p>The first solution has the best performance but less
  333.           flexibility, and is less error safe:</p>
  334.  
  335. <div class="example"><pre>
  336. RewriteEngine on
  337. RewriteCond   /your/docroot/%{REQUEST_FILENAME} <strong>!-f</strong>
  338. RewriteRule   ^(.+)                             http://<strong>webserverB</strong>.dom/$1
  339. </pre></div>
  340.  
  341.           <p>The problem here is that this will only work for pages
  342.           inside the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>. While you can add more
  343.           Conditions (for instance to also handle homedirs, etc.)
  344.           there is better variant:</p>
  345.  
  346. <div class="example"><pre>
  347. RewriteEngine on
  348. RewriteCond   %{REQUEST_URI} <strong>!-U</strong>
  349. RewriteRule   ^(.+)          http://<strong>webserverB</strong>.dom/$1
  350. </pre></div>
  351.  
  352.           <p>This uses the URL look-ahead feature of <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>.
  353.           The result is that this will work for all types of URLs
  354.           and is a safe way. But it does a performance impact on
  355.           the webserver, because for every request there is one
  356.           more internal subrequest. So, if your webserver runs on a
  357.           powerful CPU, use this one. If it is a slow machine, use
  358.           the first approach or better a <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> CGI-script.</p>
  359.         </dd>
  360.       </dl>
  361.  
  362.     </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  363. <div class="section">
  364. <h2>Archive Access Multiplexer</h2>
  365.  
  366.       
  367.  
  368.       <dl>
  369.         <dt>Description:</dt>
  370.  
  371.         <dd>
  372.           <p>Do you know the great CPAN (Comprehensive Perl Archive
  373.           Network) under <a href="http://www.perl.com/CPAN">http://www.perl.com/CPAN</a>?
  374.           This does a redirect to one of several FTP servers around
  375.           the world which carry a CPAN mirror and is approximately
  376.           near the location of the requesting client. Actually this
  377.           can be called an FTP access multiplexing service. While
  378.           CPAN runs via CGI scripts, how can a similar approach
  379.           implemented via <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>?</p>
  380.         </dd>
  381.  
  382.         <dt>Solution:</dt>
  383.  
  384.         <dd>
  385.           <p>First we notice that from version 3.0.0
  386.           <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> can
  387.           also use the "<code>ftp:</code>" scheme on redirects.
  388.           And second, the location approximation can be done by a
  389.           <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>
  390.           over the top-level domain of the client.
  391.           With a tricky chained ruleset we can use this top-level
  392.           domain as a key to our multiplexing map.</p>
  393.  
  394. <div class="example"><pre>
  395. RewriteEngine on
  396. RewriteMap    multiplex                txt:/path/to/map.cxan
  397. RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
  398. RewriteRule   ^.+\.<strong>([a-zA-Z]+)</strong>::(.*)$  ${multiplex:<strong>$1</strong>|ftp.default.dom}$2  [R,L]
  399. </pre></div>
  400.  
  401. <div class="example"><pre>
  402. ##
  403. ##  map.cxan -- Multiplexing Map for CxAN
  404. ##
  405.  
  406. de        ftp://ftp.cxan.de/CxAN/
  407. uk        ftp://ftp.cxan.uk/CxAN/
  408. com       ftp://ftp.cxan.com/CxAN/
  409.  :
  410. ##EOF##
  411. </pre></div>
  412.         </dd>
  413.       </dl>
  414.  
  415.     </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  416. <div class="section">
  417. <h2><a name="content" id="content">Content Handling</a></h2>
  418.  
  419.     
  420.  
  421.    <h3>Browser Dependent Content</h3>
  422.  
  423.       
  424.  
  425.       <dl>
  426.         <dt>Description:</dt>
  427.  
  428.         <dd>
  429.           <p>At least for important top-level pages it is sometimes
  430.           necessary to provide the optimum of browser dependent
  431.           content, i.e. one has to provide a maximum version for the
  432.           latest Netscape variants, a minimum version for the Lynx
  433.           browsers and a average feature version for all others.</p>
  434.         </dd>
  435.  
  436.         <dt>Solution:</dt>
  437.  
  438.         <dd>
  439.           <p>We cannot use content negotiation because the browsers do
  440.           not provide their type in that form. Instead we have to
  441.           act on the HTTP header "User-Agent". The following condig
  442.           does the following: If the HTTP header "User-Agent"
  443.           begins with "Mozilla/3", the page <code>foo.html</code>
  444.           is rewritten to <code>foo.NS.html</code> and and the
  445.           rewriting stops. If the browser is "Lynx" or "Mozilla" of
  446.           version 1 or 2 the URL becomes <code>foo.20.html</code>.
  447.           All other browsers receive page <code>foo.32.html</code>.
  448.           This is done by the following ruleset:</p>
  449.  
  450. <div class="example"><pre>
  451. RewriteCond %{HTTP_USER_AGENT}  ^<strong>Mozilla/3</strong>.*
  452. RewriteRule ^foo\.html$         foo.<strong>NS</strong>.html          [<strong>L</strong>]
  453.  
  454. RewriteCond %{HTTP_USER_AGENT}  ^<strong>Lynx/</strong>.*         [OR]
  455. RewriteCond %{HTTP_USER_AGENT}  ^<strong>Mozilla/[12]</strong>.*
  456. RewriteRule ^foo\.html$         foo.<strong>20</strong>.html          [<strong>L</strong>]
  457.  
  458. RewriteRule ^foo\.html$         foo.<strong>32</strong>.html          [<strong>L</strong>]
  459. </pre></div>
  460.         </dd>
  461.       </dl>
  462.  
  463.     
  464.  
  465.     <h3>Dynamic Mirror</h3>
  466.  
  467.       
  468.  
  469.       <dl>
  470.         <dt>Description:</dt>
  471.  
  472.         <dd>
  473.           <p>Assume there are nice webpages on remote hosts we want
  474.           to bring into our namespace. For FTP servers we would use
  475.           the <code>mirror</code> program which actually maintains an
  476.           explicit up-to-date copy of the remote data on the local
  477.           machine. For a webserver we could use the program
  478.           <code>webcopy</code> which acts similar via HTTP. But both
  479.           techniques have one major drawback: The local copy is
  480.           always just as up-to-date as often we run the program. It
  481.           would be much better if the mirror is not a static one we
  482.           have to establish explicitly. Instead we want a dynamic
  483.           mirror with data which gets updated automatically when
  484.           there is need (updated data on the remote host).</p>
  485.         </dd>
  486.  
  487.         <dt>Solution:</dt>
  488.  
  489.         <dd>
  490.           <p>To provide this feature we map the remote webpage or even
  491.           the complete remote webarea to our namespace by the use
  492.           of the <dfn>Proxy Throughput</dfn> feature
  493.           (flag <code>[P]</code>):</p>
  494.  
  495. <div class="example"><pre>
  496. RewriteEngine  on
  497. RewriteBase    /~quux/
  498. RewriteRule    ^<strong>hotsheet/</strong>(.*)$  <strong>http://www.tstimpreso.com/hotsheet/</strong>$1  [<strong>P</strong>]
  499. </pre></div>
  500.  
  501. <div class="example"><pre>
  502. RewriteEngine  on
  503. RewriteBase    /~quux/
  504. RewriteRule    ^<strong>usa-news\.html</strong>$   <strong>http://www.quux-corp.com/news/index.html</strong>  [<strong>P</strong>]
  505. </pre></div>
  506.         </dd>
  507.       </dl>
  508.  
  509.     
  510.  
  511.     <h3>Reverse Dynamic Mirror</h3>
  512.  
  513.       
  514.  
  515.       <dl>
  516.         <dt>Description:</dt>
  517.  
  518.         <dd>...</dd>
  519.  
  520.         <dt>Solution:</dt>
  521.  
  522.         <dd>
  523. <div class="example"><pre>
  524. RewriteEngine on
  525. RewriteCond   /mirror/of/remotesite/$1           -U
  526. RewriteRule   ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1
  527. </pre></div>
  528.         </dd>
  529.       </dl>
  530.  
  531.     
  532.  
  533.     <h3>Retrieve Missing Data from Intranet</h3>
  534.  
  535.       
  536.  
  537.       <dl>
  538.         <dt>Description:</dt>
  539.  
  540.         <dd>
  541.           <p>This is a tricky way of virtually running a corporate
  542.           (external) Internet webserver
  543.           (<code>www.quux-corp.dom</code>), while actually keeping
  544.           and maintaining its data on a (internal) Intranet webserver
  545.           (<code>www2.quux-corp.dom</code>) which is protected by a
  546.           firewall. The trick is that on the external webserver we
  547.           retrieve the requested data on-the-fly from the internal
  548.           one.</p>
  549.         </dd>
  550.  
  551.         <dt>Solution:</dt>
  552.  
  553.         <dd>
  554.           <p>First, we have to make sure that our firewall still
  555.           protects the internal webserver and that only the
  556.           external webserver is allowed to retrieve data from it.
  557.           For a packet-filtering firewall we could for instance
  558.           configure a firewall ruleset like the following:</p>
  559.  
  560. <div class="example"><pre>
  561. <strong>ALLOW</strong> Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port <strong>80</strong>
  562. <strong>DENY</strong>  Host *                 Port *     --> Host www2.quux-corp.dom Port <strong>80</strong>
  563. </pre></div>
  564.  
  565.           <p>Just adjust it to your actual configuration syntax.
  566.           Now we can establish the <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
  567.           rules which request the missing data in the background
  568.           through the proxy throughput feature:</p>
  569.  
  570. <div class="example"><pre>
  571. RewriteRule ^/~([^/]+)/?(.*)          /home/$1/.www/$2
  572. RewriteCond %{REQUEST_FILENAME}       <strong>!-f</strong>
  573. RewriteCond %{REQUEST_FILENAME}       <strong>!-d</strong>
  574. RewriteRule ^/home/([^/]+)/.www/?(.*) http://<strong>www2</strong>.quux-corp.dom/~$1/pub/$2 [<strong>P</strong>]
  575. </pre></div>
  576.         </dd>
  577.       </dl>
  578.  
  579.     
  580.  
  581.     <h3>Load Balancing</h3>
  582.  
  583.       
  584.  
  585.       <dl>
  586.         <dt>Description:</dt>
  587.  
  588.         <dd>
  589.           <p>Suppose we want to load balance the traffic to
  590.           <code>www.foo.com</code> over <code>www[0-5].foo.com</code>
  591.           (a total of 6 servers). How can this be done?</p>
  592.         </dd>
  593.  
  594.         <dt>Solution:</dt>
  595.  
  596.         <dd>
  597.           <p>There are a lot of possible solutions for this problem.
  598.           We will discuss first a commonly known DNS-based variant
  599.           and then the special one with <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>:</p>
  600.  
  601.           <ol>
  602.             <li>
  603.               <strong>DNS Round-Robin</strong>
  604.  
  605.               <p>The simplest method for load-balancing is to use
  606.               the DNS round-robin feature of <code>BIND</code>.
  607.               Here you just configure <code>www[0-9].foo.com</code>
  608.               as usual in your DNS with A(address) records, e.g.</p>
  609.  
  610. <div class="example"><pre>
  611. www0   IN  A       1.2.3.1
  612. www1   IN  A       1.2.3.2
  613. www2   IN  A       1.2.3.3
  614. www3   IN  A       1.2.3.4
  615. www4   IN  A       1.2.3.5
  616. www5   IN  A       1.2.3.6
  617. </pre></div>
  618.  
  619.               <p>Then you additionally add the following entry:</p>
  620.  
  621. <div class="example"><pre>
  622. www    IN  CNAME   www0.foo.com.
  623.        IN  CNAME   www1.foo.com.
  624.        IN  CNAME   www2.foo.com.
  625.        IN  CNAME   www3.foo.com.
  626.        IN  CNAME   www4.foo.com.
  627.        IN  CNAME   www5.foo.com.
  628.        IN  CNAME   www6.foo.com.
  629. </pre></div>
  630.  
  631.               <p>Notice that this seems wrong, but is actually an
  632.               intended feature of <code>BIND</code> and can be used
  633.               in this way. However, now when <code>www.foo.com</code> gets
  634.               resolved, <code>BIND</code> gives out <code>www0-www6</code>
  635.               - but in a slightly permutated/rotated order every time.
  636.               This way the clients are spread over the various
  637.               servers. But notice that this not a perfect load
  638.               balancing scheme, because DNS resolve information
  639.               gets cached by the other nameservers on the net, so
  640.               once a client has resolved <code>www.foo.com</code>
  641.               to a particular <code>wwwN.foo.com</code>, all
  642.               subsequent requests also go to this particular name
  643.               <code>wwwN.foo.com</code>. But the final result is
  644.               ok, because the total sum of the requests are really
  645.               spread over the various webservers.</p>
  646.             </li>
  647.  
  648.             <li>
  649.               <strong>DNS Load-Balancing</strong>
  650.  
  651.               <p>A sophisticated DNS-based method for
  652.               load-balancing is to use the program
  653.               <code>lbnamed</code> which can be found at <a href="http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html">
  654.               http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html</a>.
  655.               It is a Perl 5 program in conjunction with auxilliary
  656.               tools which provides a real load-balancing for
  657.               DNS.</p>
  658.             </li>
  659.  
  660.             <li>
  661.               <strong>Proxy Throughput Round-Robin</strong>
  662.  
  663.               <p>In this variant we use <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
  664.               and its proxy throughput feature. First we dedicate
  665.               <code>www0.foo.com</code> to be actually
  666.               <code>www.foo.com</code> by using a single</p>
  667.  
  668. <div class="example"><pre>
  669. www    IN  CNAME   www0.foo.com.
  670. </pre></div>
  671.  
  672.               <p>entry in the DNS. Then we convert
  673.               <code>www0.foo.com</code> to a proxy-only server,
  674.               i.e. we configure this machine so all arriving URLs
  675.               are just pushed through the internal proxy to one of
  676.               the 5 other servers (<code>www1-www5</code>). To
  677.               accomplish this we first establish a ruleset which
  678.               contacts a load balancing script <code>lb.pl</code>
  679.               for all URLs.</p>
  680.  
  681. <div class="example"><pre>
  682. RewriteEngine on
  683. RewriteMap    lb      prg:/path/to/lb.pl
  684. RewriteRule   ^/(.+)$ ${lb:$1}           [P,L]
  685. </pre></div>
  686.  
  687.               <p>Then we write <code>lb.pl</code>:</p>
  688.  
  689. <div class="example"><pre>
  690. #!/path/to/perl
  691. ##
  692. ##  lb.pl -- load balancing script
  693. ##
  694.  
  695. $| = 1;
  696.  
  697. $name   = "www";     # the hostname base
  698. $first  = 1;         # the first server (not 0 here, because 0 is myself)
  699. $last   = 5;         # the last server in the round-robin
  700. $domain = "foo.dom"; # the domainname
  701.  
  702. $cnt = 0;
  703. while (<STDIN>) {
  704.     $cnt = (($cnt+1) % ($last+1-$first));
  705.     $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
  706.     print "http://$server/$_";
  707. }
  708.  
  709. ##EOF##
  710. </pre></div>
  711.  
  712.               <div class="note">A last notice: Why is this useful? Seems like
  713.               <code>www0.foo.com</code> still is overloaded? The
  714.               answer is yes, it is overloaded, but with plain proxy
  715.               throughput requests, only! All SSI, CGI, ePerl, etc.
  716.               processing is completely done on the other machines.
  717.               This is the essential point.</div>
  718.             </li>
  719.  
  720.             <li>
  721.               <strong>Hardware/TCP Round-Robin</strong>
  722.  
  723.               <p>There is a hardware solution available, too. Cisco
  724.               has a beast called LocalDirector which does a load
  725.               balancing at the TCP/IP level. Actually this is some
  726.               sort of a circuit level gateway in front of a
  727.               webcluster. If you have enough money and really need
  728.               a solution with high performance, use this one.</p>
  729.             </li>
  730.           </ol>
  731.         </dd>
  732.       </dl>
  733.  
  734.     
  735.  
  736.     <h3>New MIME-type, New Service</h3>
  737.  
  738.       
  739.  
  740.       <dl>
  741.         <dt>Description:</dt>
  742.  
  743.         <dd>
  744.           <p>On the net there are a lot of nifty CGI programs. But
  745.           their usage is usually boring, so a lot of webmaster
  746.           don't use them. Even Apache's Action handler feature for
  747.           MIME-types is only appropriate when the CGI programs
  748.           don't need special URLs (actually <code>PATH_INFO</code>
  749.           and <code>QUERY_STRINGS</code>) as their input. First,
  750.           let us configure a new file type with extension
  751.           <code>.scgi</code> (for secure CGI) which will be processed
  752.           by the popular <code>cgiwrap</code> program. The problem
  753.           here is that for instance we use a Homogeneous URL Layout
  754.           (see above) a file inside the user homedirs has the URL
  755.           <code>/u/user/foo/bar.scgi</code>. But
  756.           <code>cgiwrap</code> needs the URL in the form
  757.           <code>/~user/foo/bar.scgi/</code>. The following rule
  758.           solves the problem:</p>
  759.  
  760. <div class="example"><pre>
  761. RewriteRule ^/[uge]/<strong>([^/]+)</strong>/\.www/(.+)\.scgi(.*) ...
  762. ... /internal/cgi/user/cgiwrap/~<strong>$1</strong>/$2.scgi$3  [NS,<strong>T=application/x-http-cgi</strong>]
  763. </pre></div>
  764.  
  765.           <p>Or assume we have some more nifty programs:
  766.           <code>wwwlog</code> (which displays the
  767.           <code>access.log</code> for a URL subtree and
  768.           <code>wwwidx</code> (which runs Glimpse on a URL
  769.           subtree). We have to provide the URL area to these
  770.           programs so they know on which area they have to act on.
  771.           But usually this ugly, because they are all the times
  772.           still requested from that areas, i.e. typically we would
  773.           run the <code>swwidx</code> program from within
  774.           <code>/u/user/foo/</code> via hyperlink to</p>
  775.  
  776. <div class="example"><pre>
  777. /internal/cgi/user/swwidx?i=/u/user/foo/
  778. </pre></div>
  779.  
  780.           <p>which is ugly. Because we have to hard-code
  781.           <strong>both</strong> the location of the area
  782.           <strong>and</strong> the location of the CGI inside the
  783.           hyperlink. When we have to reorganize the area, we spend a
  784.           lot of time changing the various hyperlinks.</p>
  785.         </dd>
  786.  
  787.         <dt>Solution:</dt>
  788.  
  789.         <dd>
  790.           <p>The solution here is to provide a special new URL format
  791.           which automatically leads to the proper CGI invocation.
  792.           We configure the following:</p>
  793.  
  794. <div class="example"><pre>
  795. RewriteRule   ^/([uge])/([^/]+)(/?.*)/\*  /internal/cgi/user/wwwidx?i=/$1/$2$3/
  796. RewriteRule   ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3
  797. </pre></div>
  798.  
  799.           <p>Now the hyperlink to search at
  800.           <code>/u/user/foo/</code> reads only</p>
  801.  
  802. <div class="example"><pre>
  803. HREF="*"
  804. </pre></div>
  805.  
  806.           <p>which internally gets automatically transformed to</p>
  807.  
  808. <div class="example"><pre>
  809. /internal/cgi/user/wwwidx?i=/u/user/foo/
  810. </pre></div>
  811.  
  812.           <p>The same approach leads to an invocation for the
  813.           access log CGI program when the hyperlink
  814.           <code>:log</code> gets used.</p>
  815.         </dd>
  816.       </dl>
  817.  
  818.     
  819.  
  820.     <h3>On-the-fly Content-Regeneration</h3>
  821.  
  822.       
  823.  
  824.       <dl>
  825.         <dt>Description:</dt>
  826.  
  827.         <dd>
  828.           <p>Here comes a really esoteric feature: Dynamically
  829.           generated but statically served pages, i.e. pages should be
  830.           delivered as pure static pages (read from the filesystem
  831.           and just passed through), but they have to be generated
  832.           dynamically by the webserver if missing. This way you can
  833.           have CGI-generated pages which are statically served unless
  834.           one (or a cronjob) removes the static contents. Then the
  835.           contents gets refreshed.</p>
  836.         </dd>
  837.  
  838.         <dt>Solution:</dt>
  839.  
  840.         <dd>
  841.           This is done via the following ruleset:
  842.  
  843. <div class="example"><pre>
  844. RewriteCond %{REQUEST_FILENAME}   <strong>!-s</strong>
  845. RewriteRule ^page\.<strong>html</strong>$          page.<strong>cgi</strong>   [T=application/x-httpd-cgi,L]
  846. </pre></div>
  847.  
  848.           <p>Here a request to <code>page.html</code> leads to a
  849.           internal run of a corresponding <code>page.cgi</code> if
  850.           <code>page.html</code> is still missing or has filesize
  851.           null. The trick here is that <code>page.cgi</code> is a
  852.           usual CGI script which (additionally to its <code>STDOUT</code>)
  853.           writes its output to the file <code>page.html</code>.
  854.           Once it was run, the server sends out the data of
  855.           <code>page.html</code>. When the webmaster wants to force
  856.           a refresh the contents, he just removes
  857.           <code>page.html</code> (usually done by a cronjob).</p>
  858.         </dd>
  859.       </dl>
  860.  
  861.     
  862.  
  863.     <h3>Document With Autorefresh</h3>
  864.  
  865.       
  866.  
  867.       <dl>
  868.         <dt>Description:</dt>
  869.  
  870.         <dd>
  871.           <p>Wouldn't it be nice while creating a complex webpage if
  872.           the webbrowser would automatically refresh the page every
  873.           time we write a new version from within our editor?
  874.           Impossible?</p>
  875.         </dd>
  876.  
  877.         <dt>Solution:</dt>
  878.  
  879.         <dd>
  880.           <p>No! We just combine the MIME multipart feature, the
  881.           webserver NPH feature and the URL manipulation power of
  882.           <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>. First, we establish a new
  883.           URL feature: Adding just <code>:refresh</code> to any
  884.           URL causes this to be refreshed every time it gets
  885.           updated on the filesystem.</p>
  886.  
  887. <div class="example"><pre>
  888. RewriteRule   ^(/[uge]/[^/]+/?.*):refresh  /internal/cgi/apache/nph-refresh?f=$1
  889. </pre></div>
  890.  
  891.           <p>Now when we reference the URL</p>
  892.  
  893. <div class="example"><pre>
  894. /u/foo/bar/page.html:refresh
  895. </pre></div>
  896.  
  897.           <p>this leads to the internal invocation of the URL</p>
  898.  
  899. <div class="example"><pre>
  900. /internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
  901. </pre></div>
  902.  
  903.           <p>The only missing part is the NPH-CGI script. Although
  904.           one would usually say "left as an exercise to the reader"
  905.           ;-) I will provide this, too.</p>
  906.  
  907. <div class="example"><pre>
  908. #!/sw/bin/perl
  909. ##
  910. ##  nph-refresh -- NPH/CGI script for auto refreshing pages
  911. ##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
  912. ##
  913. $| = 1;
  914.  
  915. #   split the QUERY_STRING variable
  916. @pairs = split(/&/, $ENV{'QUERY_STRING'});
  917. foreach $pair (@pairs) {
  918.     ($name, $value) = split(/=/, $pair);
  919.     $name =~ tr/A-Z/a-z/;
  920.     $name = 'QS_' . $name;
  921.     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  922.     eval "\$$name = \"$value\"";
  923. }
  924. $QS_s = 1 if ($QS_s eq '');
  925. $QS_n = 3600 if ($QS_n eq '');
  926. if ($QS_f eq '') {
  927.     print "HTTP/1.0 200 OK\n";
  928.     print "Content-type: text/html\n\n";
  929.     print "&lt;b&gt;ERROR&lt;/b&gt;: No file given\n";
  930.     exit(0);
  931. }
  932. if (! -f $QS_f) {
  933.     print "HTTP/1.0 200 OK\n";
  934.     print "Content-type: text/html\n\n";
  935.     print "&lt;b&gt;ERROR&lt;/b&gt;: File $QS_f not found\n";
  936.     exit(0);
  937. }
  938.  
  939. sub print_http_headers_multipart_begin {
  940.     print "HTTP/1.0 200 OK\n";
  941.     $bound = "ThisRandomString12345";
  942.     print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
  943.     &print_http_headers_multipart_next;
  944. }
  945.  
  946. sub print_http_headers_multipart_next {
  947.     print "\n--$bound\n";
  948. }
  949.  
  950. sub print_http_headers_multipart_end {
  951.     print "\n--$bound--\n";
  952. }
  953.  
  954. sub displayhtml {
  955.     local($buffer) = @_;
  956.     $len = length($buffer);
  957.     print "Content-type: text/html\n";
  958.     print "Content-length: $len\n\n";
  959.     print $buffer;
  960. }
  961.  
  962. sub readfile {
  963.     local($file) = @_;
  964.     local(*FP, $size, $buffer, $bytes);
  965.     ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
  966.     $size = sprintf("%d", $size);
  967.     open(FP, "&lt;$file");
  968.     $bytes = sysread(FP, $buffer, $size);
  969.     close(FP);
  970.     return $buffer;
  971. }
  972.  
  973. $buffer = &readfile($QS_f);
  974. &print_http_headers_multipart_begin;
  975. &displayhtml($buffer);
  976.  
  977. sub mystat {
  978.     local($file) = $_[0];
  979.     local($time);
  980.  
  981.     ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
  982.     return $mtime;
  983. }
  984.  
  985. $mtimeL = &mystat($QS_f);
  986. $mtime = $mtime;
  987. for ($n = 0; $n &lt; $QS_n; $n++) {
  988.     while (1) {
  989.         $mtime = &mystat($QS_f);
  990.         if ($mtime ne $mtimeL) {
  991.             $mtimeL = $mtime;
  992.             sleep(2);
  993.             $buffer = &readfile($QS_f);
  994.             &print_http_headers_multipart_next;
  995.             &displayhtml($buffer);
  996.             sleep(5);
  997.             $mtimeL = &mystat($QS_f);
  998.             last;
  999.         }
  1000.         sleep($QS_s);
  1001.     }
  1002. }
  1003.  
  1004. &print_http_headers_multipart_end;
  1005.  
  1006. exit(0);
  1007.  
  1008. ##EOF##
  1009. </pre></div>
  1010.         </dd>
  1011.       </dl>
  1012.  
  1013.     
  1014.  
  1015.     <h3>Mass Virtual Hosting</h3>
  1016.  
  1017.       
  1018.  
  1019.       <dl>
  1020.         <dt>Description:</dt>
  1021.  
  1022.         <dd>
  1023.           <p>The <code class="directive"><a href="../mod/core.html#virtualhost"><VirtualHost></a></code> feature of Apache is nice
  1024.           and works great when you just have a few dozens
  1025.           virtual hosts. But when you are an ISP and have hundreds of
  1026.           virtual hosts to provide this feature is not the best
  1027.           choice.</p>
  1028.         </dd>
  1029.  
  1030.         <dt>Solution:</dt>
  1031.  
  1032.         <dd>
  1033.           <p>To provide this feature we map the remote webpage or even
  1034.           the complete remote webarea to our namespace by the use
  1035.           of the <dfn>Proxy Throughput</dfn> feature (flag <code>[P]</code>):</p>
  1036.  
  1037. <div class="example"><pre>
  1038. ##
  1039. ##  vhost.map
  1040. ##
  1041. www.vhost1.dom:80  /path/to/docroot/vhost1
  1042. www.vhost2.dom:80  /path/to/docroot/vhost2
  1043.      :
  1044. www.vhostN.dom:80  /path/to/docroot/vhostN
  1045. </pre></div>
  1046.  
  1047. <div class="example"><pre>
  1048. ##
  1049. ##  httpd.conf
  1050. ##
  1051.     :
  1052. #   use the canonical hostname on redirects, etc.
  1053. UseCanonicalName on
  1054.  
  1055.     :
  1056. #   add the virtual host in front of the CLF-format
  1057. CustomLog  /path/to/access_log  "%{VHOST}e %h %l %u %t \"%r\" %>s %b"
  1058.     :
  1059.  
  1060. #   enable the rewriting engine in the main server
  1061. RewriteEngine on
  1062.  
  1063. #   define two maps: one for fixing the URL and one which defines
  1064. #   the available virtual hosts with their corresponding
  1065. #   DocumentRoot.
  1066. RewriteMap    lowercase    int:tolower
  1067. RewriteMap    vhost        txt:/path/to/vhost.map
  1068.  
  1069. #   Now do the actual virtual host mapping
  1070. #   via a huge and complicated single rule:
  1071. #
  1072. #   1. make sure we don't map for common locations
  1073. RewriteCond   %{REQUEST_URI}  !^/commonurl1/.*
  1074. RewriteCond   %{REQUEST_URI}  !^/commonurl2/.*
  1075.     :
  1076. RewriteCond   %{REQUEST_URI}  !^/commonurlN/.*
  1077. #
  1078. #   2. make sure we have a Host header, because
  1079. #      currently our approach only supports
  1080. #      virtual hosting through this header
  1081. RewriteCond   %{HTTP_HOST}  !^$
  1082. #
  1083. #   3. lowercase the hostname
  1084. RewriteCond   ${lowercase:%{HTTP_HOST}|NONE}  ^(.+)$
  1085. #
  1086. #   4. lookup this hostname in vhost.map and
  1087. #      remember it only when it is a path
  1088. #      (and not "NONE" from above)
  1089. RewriteCond   ${vhost:%1}  ^(/.*)$
  1090. #
  1091. #   5. finally we can map the URL to its docroot location
  1092. #      and remember the virtual host for logging puposes
  1093. RewriteRule   ^/(.*)$   %1/$1  [E=VHOST:${lowercase:%{HTTP_HOST}}]
  1094.     :
  1095. </pre></div>
  1096.         </dd>
  1097.       </dl>
  1098.  
  1099.     
  1100.  
  1101.   </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
  1102. <div class="section">
  1103. <h2><a name="access" id="access">Access Restriction</a></h2>
  1104.  
  1105.     
  1106.  
  1107.     <h3>Host Deny</h3>
  1108.  
  1109.       
  1110.  
  1111.       <dl>
  1112.         <dt>Description:</dt>
  1113.  
  1114.         <dd>
  1115.           <p>How can we forbid a list of externally configured hosts
  1116.           from using our server?</p>
  1117.         </dd>
  1118.  
  1119.         <dt>Solution:</dt>
  1120.  
  1121.         <dd>
  1122.           <p>For Apache >= 1.3b6:</p>
  1123.  
  1124. <div class="example"><pre>
  1125. RewriteEngine on
  1126. RewriteMap    hosts-deny  txt:/path/to/hosts.deny
  1127. RewriteCond   ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
  1128. RewriteCond   ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
  1129. RewriteRule   ^/.*  -  [F]
  1130. </pre></div>
  1131.  
  1132.           <p>For Apache <= 1.3b6:</p>
  1133.  
  1134. <div class="example"><pre>
  1135. RewriteEngine on
  1136. RewriteMap    hosts-deny  txt:/path/to/hosts.deny
  1137. RewriteRule   ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
  1138. RewriteRule   !^NOT-FOUND/.* - [F]
  1139. RewriteRule   ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
  1140. RewriteRule   !^NOT-FOUND/.* - [F]
  1141. RewriteRule   ^NOT-FOUND/(.*)$ /$1
  1142. </pre></div>
  1143.  
  1144. <div class="example"><pre>
  1145. ##
  1146. ##  hosts.deny
  1147. ##
  1148. ##  ATTENTION! This is a map, not a list, even when we treat it as such.
  1149. ##             mod_rewrite parses it for key/value pairs, so at least a
  1150. ##             dummy value "-" must be present for each entry.
  1151. ##
  1152.  
  1153. 193.102.180.41 -
  1154. bsdti1.sdm.de  -
  1155. 192.76.162.40  -
  1156. </pre></div>
  1157.         </dd>
  1158.       </dl>
  1159.  
  1160.     
  1161.  
  1162.     <h3>Proxy Deny</h3>
  1163.  
  1164.       
  1165.  
  1166.       <dl>
  1167.         <dt>Description:</dt>
  1168.  
  1169.         <dd>
  1170.           <p>How can we forbid a certain host or even a user of a
  1171.           special host from using the Apache proxy?</p>
  1172.         </dd>
  1173.  
  1174.         <dt>Solution:</dt>
  1175.  
  1176.         <dd>
  1177.           <p>We first have to make sure <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
  1178.           is below(!) <code class="module"><a href="../mod/mod_proxy.html">mod_proxy</a></code> in the Configuration
  1179.           file when compiling the Apache webserver. This way it gets
  1180.           called <em>before</em> <code class="module"><a href="../mod/mod_proxy.html">mod_proxy</a></code>. Then we
  1181.           configure the following for a host-dependent deny...</p>
  1182.  
  1183. <div class="example"><pre>
  1184. RewriteCond %{REMOTE_HOST} <strong>^badhost\.mydomain\.com$</strong>
  1185. RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]
  1186. </pre></div>
  1187.  
  1188.           <p>...and this one for a user@host-dependent deny:</p>
  1189.  
  1190. <div class="example"><pre>
  1191. RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST}  <strong>^badguy@badhost\.mydomain\.com$</strong>
  1192. RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]
  1193. </pre></div>
  1194.         </dd>
  1195.       </dl>
  1196.  
  1197.     
  1198.  
  1199.     <h3>Special Authentication Variant</h3>
  1200.  
  1201.       
  1202.  
  1203.       <dl>
  1204.         <dt>Description:</dt>
  1205.  
  1206.         <dd>
  1207.           <p>Sometimes a very special authentication is needed, for
  1208.           instance a authentication which checks for a set of
  1209.           explicitly configured users. Only these should receive
  1210.           access and without explicit prompting (which would occur
  1211.           when using the Basic Auth via <code class="module"><a href="../mod/mod_auth.html">mod_auth</a></code>).</p>
  1212.         </dd>
  1213.  
  1214.         <dt>Solution:</dt>
  1215.  
  1216.         <dd>
  1217.           <p>We use a list of rewrite conditions to exclude all except
  1218.           our friends:</p>
  1219.  
  1220. <div class="example"><pre>
  1221. RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^friend1@client1.quux-corp\.com$</strong>
  1222. RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^friend2</strong>@client2.quux-corp\.com$
  1223. RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^friend3</strong>@client3.quux-corp\.com$
  1224. RewriteRule ^/~quux/only-for-friends/      -                                 [F]
  1225. </pre></div>
  1226.         </dd>
  1227.       </dl>
  1228.  
  1229.     
  1230.  
  1231.     <h3>Referer-based Deflector</h3>
  1232.  
  1233.       
  1234.  
  1235.       <dl>
  1236.         <dt>Description:</dt>
  1237.  
  1238.         <dd>
  1239.           <p>How can we program a flexible URL Deflector which acts
  1240.           on the "Referer" HTTP header and can be configured with as
  1241.           many referring pages as we like?</p>
  1242.         </dd>
  1243.  
  1244.         <dt>Solution:</dt>
  1245.  
  1246.         <dd>
  1247.           <p>Use the following really tricky ruleset...</p>
  1248.  
  1249. <div class="example"><pre>
  1250. RewriteMap  deflector txt:/path/to/deflector.map
  1251.  
  1252. RewriteCond %{HTTP_REFERER} !=""
  1253. RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
  1254. RewriteRule ^.* %{HTTP_REFERER} [R,L]
  1255.  
  1256. RewriteCond %{HTTP_REFERER} !=""
  1257. RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
  1258. RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]
  1259. </pre></div>
  1260.  
  1261.           <p>... in conjunction with a corresponding rewrite
  1262.           map:</p>
  1263.  
  1264. <div class="example"><pre>
  1265. ##
  1266. ##  deflector.map
  1267. ##
  1268.  
  1269. http://www.badguys.com/bad/index.html    -
  1270. http://www.badguys.com/bad/index2.html   -
  1271. http://www.badguys.com/bad/index3.html   http://somewhere.com/
  1272. </pre></div>
  1273.  
  1274.           <p>This automatically redirects the request back to the
  1275.           referring page (when "<code>-</code>" is used as the value
  1276.           in the map) or to a specific URL (when an URL is specified
  1277.           in the map as the second argument).</p>
  1278.         </dd>
  1279.       </dl>
  1280.  
  1281.     
  1282.  
  1283.   </div></div>
  1284. <div class="bottomlang">
  1285. <p><span>Available Languages: </span><a href="../en/rewrite/rewrite_guide_advanced.html" title="English"> en </a></p>
  1286. </div><div id="footer">
  1287. <p class="apache">Copyright 1995-2006 The Apache Software Foundation or its licensors, as applicable.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
  1288. <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
  1289. </body></html>